<?php

namespace App\Models\Customer;

use App\Models\Concerns\ScopeFilterable;
use App\Models\Panx\Device;
use App\Models\Panx\Product;
use App\Models\Panx\Record;
use App\Models\Panx\RecordType;
use App\Models\Panx\SkinDetector;
use App\Models\Store\SkinRecord;
use App\Models\Store\Store;
use App\Services\Locale\Language;
use App\Services\Utils\ActionLogger;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\Hash;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Support\Str;
use Tymon\JWTAuth\Contracts\JWTSubject as AuthenticatableUserContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;

/**
 * @property string remember_token
 * @property string uuid
 * @property Customer customer
 * @property int customer_id
 * @property int store_id
 * @property int id
 * @property float $latitude
 * @property float $longitude
 * @property Carbon $last_active_at - not null default 1970-01-02 00:00:00
 * @property int $alive_seconds
 * @property Store store
 * @property Device $device - 早期无 device_id 的数据是错误的
 * @property bool is_debug
 * @property bool enabled
 * @property string language
 * @property string password
 * @property string account
 * @property Collection skinDetectors
 * @property Collection skinRecords
 * @property Carbon created_at
 * @property Carbon last_login_at
 * @property Carbon password_modified_at
 * @property Collection records
 * @property string location
 * @property string product_try_on_count
 * @property string skin_record_count
 * @mixin Builder
 *
 * @method static self filterAccountKeyword($account_keyword)
 * @method static self filterEnabled($enabled)
 * @method static self filterStoreId($store_keyword)
 * @method static self filterCustomerId($customer_keyword)
 */
class DeviceAccount extends Authenticatable implements
    CanResetPasswordContract,
    AuthenticatableUserContract
{
    use ScopeFilterable;
//    use ActionLogger;

    const DEFAULT_PASSWORD = 'fghjkl';

    const GUARD_NAME = 'app';

    const IS_ENABLED = 1; // 账号可用

    protected $table = 'device_accounts';

    protected $guarded = [];

    protected $hidden = ['password', 'remember_token', 'reset_token'];

    public $casts = [
        'skin_detector_id'     => 'int',
        'customer_id'          => 'int',
        'is_debug'             => 'bool',
        'enabled'              => 'bool',
        'last_active_at'       => 'datetime',
        'password_modified_at' => 'datetime',
        'last_login_at'        => 'datetime',
    ];

    const ALIVE_SECONDS_MAX = 4294967295; // int 无符号最大值

    /**
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function customer()
    {
        return $this->belongsTo(Customer::class, 'customer_id', 'id');
    }

    /**
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function store()
    {
        return $this->belongsTo(Store::class, 'store_id', 'id');
    }

    /**
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function device()
    {
        return $this->belongsTo(Device::class, 'device_id', 'id');
    }

    public function skinRecords()
    {
        return $this->hasMany(SkinRecord::class, 'device_account_id', 'id');
    }

    /**
     * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
     */
    public function skinDetectors()
    {
        return $this->belongsToMany(SkinDetector::class, 'device_account_pivot_skin_detector', 'device_account_id','skin_detector_id');
    }

    /**
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function records()
    {
        return $this->hasMany(Record::class, 'recorderable_id', 'id')
            ->where([
                'recorderable_type' => class_basename(DeviceAccount::class),
                'record_type_id'    => RecordType::PRODUCT_TRYON
            ]);
    }

    /**
     * @return \Illuminate\Database\Eloquent\Relations\MorphToMany
     */
    public function appBanners()
    {
        return $this->morphToMany(Bannerable::class, 'bannerable');
    }


    /**
     * @return \Illuminate\Database\Eloquent\Relations\MorphToMany
     */
    public function banners()
    {
        return $this->morphToMany(Banner::class, 'bannerable');
    }

    /**
     * @return \Illuminate\Database\Eloquent\Relations\MorphToMany
     */
    public function products()
    {
        return $this->morphToMany(Product::class, 'records');
    }

    /**
     * @param $password
     */
    public function setPasswordAttribute($password)
    {
        if ($password) {
            $this->attributes['password'] = Hash::make($password);
        }
    }

    /**
     * @return mixed
     */
    public function getJWTIdentifier()
    {
        return $this->getKey(); // Eloquent model method
    }

    /**
     * @return array
     */
    public function getJWTCustomClaims()
    {
        return [];
    }

    /**
     * @param null|string $account
     * @return DeviceAccount|null
     */
    public static function findByAccount(?string $account): ?self
    {
        return (new self)->where('account', $account)->first();
    }

    /**
     * @param null|string $token
     * @return DeviceAccount|null
     */
    public static function findByToken(?string $token): ?self
    {
        return (new self)->where('remember_token', $token)->first();
    }

    /**
     * 是否应该限制单机登录
     *
     * @return bool
     */
    public function shouldLimitSingleLogin(): bool
    {
        if ($this->is_debug) {
            return false;
        }

        if (config('app.debug')) {
            return false;
        }

        return true;
    }

    /**
     * @return bool
     */
    public function unbindDevice(): bool
    {
        return $this->uuid ? $this->update(['uuid' => null]) : false;
    }

    public function adverts()
    {
        return $this->belongsToMany(Advert::class,'advert_pivot_device_account','device_account_id','advert_id');
    }
    
    public function refreshRememberToken(string $token): bool
    {
        return $this->update(['remember_token' => $token]);
    }

    /**
     * @used-by filterAccountKeyword() - 筛选设备账号名称
     *
     * @param Builder $query
     * @param $account_keyword
     * @return Builder
     */
    public function scopeFilterAccountKeyword(Builder $query, $account_keyword)
    {
        if (! $account_keyword) return $query;

        return $query->where('account', 'like', '%'. $account_keyword .'%');
    }

    /**
     * @used-by filterEnabled() - 筛选设备账号名称
     *
     * @param Builder $query
     * @param $enabled
     * @return Builder
     */
    public function scopeFilterEnabled(Builder $query, $enabled)
    {
        if (! isset($enabled)) return $query;

        return $query->where('enabled', $enabled);
    }

    /**
     * @used-by filterStoreId() - 筛选设备账号关联店铺的名称
     *
     * @param Builder $query
     * @param $store_id
     * @return Builder
     */
    public function scopeFilterStoreId(Builder $query, $store_id)
    {
        if(!isset($store_id)) return $query;

        return $query->where('store_id', $store_id);
    }

    /**
     * @used-by filterCustomerId() - 筛选设备账号关联店铺的名称
     *
     * @param Builder $query
     * @param $customer_id
     * @return Builder
     */
    public function scopeFilterCustomerId(Builder $query, $customer_id)
    {
        if(!isset($customer_id)) return $query;

        return $query->where('customer_id',$customer_id);
    }
}
